const { SpawnCreep, NavigateTo, FullStructure, HarvestEnergy, FullUpgradeController, FullRepair, FullBuild } = require("./CommonBehavior");
const { HS, RoleType, RoomManager } = require("./Homestead");
const { INTENT_RETURN_FAIL, INTENT_NO_CONTROL_OBJ } = require("./IntentStack");
const { CreepBehavior, Behavior, IntentCreep } = require("./Overtick");
const { Util } = require("./Util");


/**
 * 协议行为
 */


let GetEnergy = class GetEnergy extends CreepBehavior{
    do(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }

        //优先 通用容器 Storage 或 Container
        let boxs = creep.room.find(FIND_STRUCTURES,{
            filter:function(i){
                if(!(i.structureType == STRUCTURE_CONTAINER
                || i.structureType == STRUCTURE_STORAGE
                || i.structureType == STRUCTURE_LINK)){
                    return false;
                }

                if(i.store[RESOURCE_ENERGY] == 0){
                    return false;
                }
                return true;
            }
        });
        let bestbox = creep.pos.findClosestByRange(boxs);
        if(bestbox != null){
            this.todo(NavigateTo,bestbox.pos,{range:1});
            this.withdraw(bestbox,RESOURCE_ENERGY);
            return;
        }

        //尝试获取能量
        let sources = creep.room.find(FIND_SOURCES);

        let target = Util.randomArray(sources);

        this.todo(HarvestEnergy,target);

    }

    finished(){

    }
}

// ================================ Role Behavior

let Transfer = class Transfer extends CreepBehavior{

    static namespace(){
        return "HomeStead";
    }

    do(){
        let creep = this.getCreep();
        if(creep == undefined){
            this.throwUp(INTENT_NO_CONTROL_OBJ);
            return;
        }

        let room = HS.getCreepRoom(this);

        //先填充Spawn
        let spawns = _.filter(Game.spawns,(i) => {
            return i.room == room && i.store[RESOURCE_ENERGY] < i.store.getCapacity(RESOURCE_ENERGY);
        });
        if(spawns.length > 0){
            if(creep.store[RESOURCE_ENERGY] < creep.store.getCapacity()){
                this.todo(GetEnergy);
            }
            let targetSpawn = Util.randomArray(spawns);
            this.todo(FullStructure,targetSpawn,RESOURCE_ENERGY);
            return;
        }

        //再填充Extension

        let notEnoughExtension = creep.room.find(FIND_MY_STRUCTURES,{
            filter: (i) => i.structureType == STRUCTURE_EXTENSION && i.store[RESOURCE_ENERGY] < i.store.getCapacity(RESOURCE_ENERGY)
        })
        //进行排序
        notEnoughExtension.sort(function(a,b){
            return creep.pos.getRangeTo(a) - creep.pos.getRangeTo(b);
        })
        if(notEnoughExtension.length > 0){
            this.todo(GetEnergy);
            for(let i = 0; i < creep.store.getUsedCapacity(RESOURCE_ENERGY) / 50; i++){
                let best = notEnoughExtension[i];
                if(best == undefined){
                    continue;
                }
                this.todo(NavigateTo,best.pos,{range:1});
                this.todo(FullStructure,best,RESOURCE_ENERGY);   
            }

            return;
        }
        

        //填充Tower
        let towers = creep.room.find(FIND_MY_STRUCTURES,{
            filter:function(i){
                return i.structureType == STRUCTURE_TOWER && (i.store[RESOURCE_ENERGY] < i.store.getCapacity(RESOURCE_ENERGY));
            }
        })
        if(towers.length > 0){
            if(creep.store[RESOURCE_ENERGY] < creep.store.getCapacity()){
                this.todo(GetEnergy);
            }
            this.todo(FullStructure,towers[0],RESOURCE_ENERGY);
            return;
        }


        //有工地的先修建筑 最近的一个修建任务
        let buildSitesPos = [];for(let id in Game.constructionSites){
            buildSitesPos.push(Game.constructionSites[id]);
        }
        let bestBuildSite = creep.pos.findClosestByRange(buildSitesPos);
        if(bestBuildSite != null){
            if(creep.store[RESOURCE_ENERGY] < creep.store.getCapacity()){
                this.todo(GetEnergy);
            }
            this.todo(FullBuild,bestBuildSite);
            return;
        }

        let containers = Util.mget(() => Memory.Homestead.RoomManager.rooms[creep.room.name].containers,{});
        //将 O 中 的能量或矿 运输到 Storage
        let OC = Util.filterObject(containers,function(k,v){
            //输出类型
            if(v.type == -1 || v.type == 2){
                return false;
            }
            v.target = Game.getObjectById(k);
            //确保当中有物品
            return v.target.store.getUsedCapacity() > creep.store.getCapacity();
        })
        let IC = Util.filterObject(containers,function(k,v){
            //输出类型
            if(v.type == 0 || v.type == 1){
                return false;
            }
            v.target = Game.getObjectById(k);
            //确保没有满载
            return v.target.store.getFreeCapacity() > creep.store.getCapacity();
        })

        if(Object.keys(OC).length > 0){
            if(creep.store.getFreeCapacity() != creep.store.getCapacity()){
                this.todo(NavigateTo,creep.room.storage.pos,{range:1});
                this.transfer(creep.room.storage,RESOURCE_ENERGY);
            }
            this.todo(NavigateTo,OC[Object.keys(OC)[0]].target.pos,{range:1});
            this.withdraw(OC[Object.keys(OC)[0]].target,RESOURCE_ENERGY);
        }else if(Object.keys(IC).length > 0){
            this.todo(GetEnergy);
        }else{
            return;
        }

        //决定运输到哪里
        if(Object.keys(IC).length > 0){//将 Storage 中的能量送至 I 类 Container
            if(creep.store[RESOURCE_ENERGY] < creep.store.getCapacity()){
                this.todo(GetEnergy);
            }
            this.todo(NavigateTo,IC[Object.keys(IC)[0]].target.pos,{range:1});
            this.transfer(IC[Object.keys(IC)[0]].target,RESOURCE_ENERGY);
        }else{//运送到Storage
            this.todo(NavigateTo,creep.room.storage.pos,{range:1});
            this.transfer(creep.room.storage,RESOURCE_ENERGY);
            return;
        }
        

        

        
    }

    exception(e){
        switch(e.code){
            default:
                e.printStackTrace(`${this.getCreepName()} 未处理的异常`);
        }
    }

    finished(){

    }
}

let Upgrader = class Upgrader extends CreepBehavior{
    do(){
        let creep = this.getCreep();
        if(creep.store[RESOURCE_ENERGY] == 0){
            this.todo(GetEnergy);
        }

        //有工地的先修建筑 最近的一个修建任务
        let buildSitesPos = [];for(let id in Game.constructionSites){
            buildSitesPos.push(Game.constructionSites[id]);
        }
        let bestBuildSite = creep.pos.findClosestByRange(buildSitesPos);
        if(bestBuildSite != null){
            // this.todo(FullBuild,bestBuildSite);
            // return;
        }

        this.todo(NavigateTo,HS.getCreepRoom(this).controller.pos,{range:3});

        //升级到身上的能量用完
        this.todo(FullUpgradeController,HS.getCreepRoom(this).controller);
    }

    exception(e){
        switch(e.code){
            default:
                e.printStackTrace(`${this.getCreepName()} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
}

let Fixer = class Fixer extends CreepBehavior{
    do(){
        let creep = this.getCreep();
        if(creep == undefined){
            return;
        }

        //计算creep能力
        /**
         * 1 work
         * build 5点 5能量
         * Fix 100耐久 1能量
         */

        //能够修复的最大hits
        let fixMaxHits = HS.getCreepBody(this,true)[WORK] * 100 * creep.store.getCapacity(RESOURCE_ENERGY);

        let needFixs = creep.room.find(FIND_STRUCTURES,{
            filter:(i) => {
                if(i.hits / i.hitsMax < 0.8){
                    return true;
                }

                if(i.hitsMax - i.hits < fixMaxHits){
                    return false;
                }


                return true;
            }
        })

        if(needFixs.length != 0){
            //重新排序
            needFixs.sort(function(a,b){
                return a.hits/a.hitsMax - b.hits/b.hitsMax;
            })

            if(creep.store[RESOURCE_ENERGY] == 0){
                this.todo(GetEnergy);
            }
            this.todo(NavigateTo,needFixs[0],{range:3});
            this.todo(FullRepair,needFixs[0]);
            return;
            
        }

        //Build
        //有工地的先修建筑 最近的一个修建任务
        let buildSitesPos = [];for(let id in Game.constructionSites){
            buildSitesPos.push(Game.constructionSites[id]);
        }
        let bestBuildSite = creep.pos.findClosestByRange(buildSitesPos);
        if(bestBuildSite != null){
            if(creep.store[RESOURCE_ENERGY] < creep.store.getCapacity()){
                this.todo(GetEnergy);
            }
            this.todo(FullBuild,bestBuildSite);
            return;
        }

    }

    exception(e){
        switch(e.code){
            default:
                e.printStackTrace(`${this.getCreepName()} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
}

let Harvester = class Harvester extends CreepBehavior{
    do(){
        let creep = this.getCreep();

        if(creep == undefined){
            this.throw(INTENT_NO_CONTROL_OBJ);
            return;
        }


        let TransferToBox = class TransferToBox extends CreepBehavior{
            do(){
                //优先 通用容器 Storage 或 Container
                let creep = this.getCreep();
                if(creep == undefined){
                    this.throwUp(INTENT_NO_CONTROL_OBJ);
                    return;
                }


                let limit = 50;
                if(creep.room.storage != undefined){
                    limit = creep.pos.getRangeTo(creep.room.storage);
                }
                let boxs = creep.room.find(FIND_STRUCTURES,{
                    filter:function(i){
                        if(!(i.structureType == STRUCTURE_CONTAINER
                        || i.structureType == STRUCTURE_STORAGE
                        || i.structureType == STRUCTURE_LINK)){
                            return false;
                        }
                        //太远的不去
                        let range = creep.pos.getRangeTo(i);
                        if(range > limit){
                            return false;
                        }

                        if(i.store.getFreeCapacity(RESOURCE_ENERGY) == 0){
                            return false;
                        }
                        return true;
                    }
                });

                if(boxs.length == 0){
                    this.throwUp("NO_BOX_COULD_SAVE");
                    return;
                }

                boxs.sort(function(a,b){
                    //Link 优先
                    let getLevel = function(target){
                        switch(target.structureType){
                            case STRUCTURE_LINK:return 0;
                            case STRUCTURE_CONTAINER:return 1;
                            case STRUCTURE_STORAGE:return 2;
                            default:return 99;
                        }
                    }
                    return getLevel(a)-getLevel(b);
                });
                // let bestbox = creep.pos.findClosestByRange(boxs);
                this.todo(NavigateTo,boxs[0].pos,{range:1});
                this.transfer(boxs[0],RESOURCE_ENERGY);
                return;
            }
        }

        if(creep.store[RESOURCE_ENERGY] > 0){
            this.todo(TransferToBox);
            return;
        }

        if(creep.store[RESOURCE_ENERGY] == 0){
            //决定却哪里挖 最近的可用的
            let sources = RoomManager.getRoomData(creep.room).sources;
            if(sources == undefined){
                return;
            }

            // let format = Util.analysisData(sources,function(id,data){
            //     let x = data.x;
            //     let y = data.y;
            //     let harvestPos = Util.analysisData(data.harvestPos,function(i){
            //         return creep.room.getPositionAt(i.x,i,y);
            //     });

            //     return{
            //         pos:creep.room.getPositionAt(x,y),
            //     }
            // })

            // let targetSource;
            // for(let id in sources){
            //     let p = creep.room.getPositionAt(sources[id].x,sources[id].y);

            // }


            let target = creep.pos.findClosestByRange(FIND_SOURCES);
            this.todo(NavigateTo,target.pos,{range:1})
            this.todo(HarvestEnergy,target);
            
        }


        

        this.todo(TransferToBox);        

    }

    exception(e){
        switch(e.code){
            default:
                e.printStackTrace(`${this.getCreepName()} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
}


let HomesteadDefault = class HomesteadDefault extends CreepBehavior{
    do(){
        let creep = this.getCreep();
        if(creep != undefined && creep.spawning == false){
            //开始任务
            switch(HS.getCreepType(this)){
                case RoleType.Transfer:
                    this.todo(Transfer);
                    return;
                case RoleType.Upgrader:
                    this.todo(Upgrader);
                    return;
                case RoleType.Fixer:
                    this.todo(Fixer)
                    return;
                case RoleType.Harvester:
                    this.todo(Harvester)
                    return;
                    default:
                    this.throw(`未知的角色类型 ${HS.getCreepType(this)}`);
                    return;
            }
        }

        //Creep 没有出生

        //获取房间
        let room = HS.getCreepRoom(this);

        //获取房间的Spawn
        let spawns = _.filter(Game.spawns,(i) => i.room == room);

        //选择一个Spawn出生
        //Need Optimization 随机
        let targetSpawn = Util.randomArray(spawns);

        //获取body
        let body = HS.getCreepBody(this);
        
    
        //Transfer 优先spawn
        let myType = HS.getCreepType(this);
        if(myType == RoleType.Transfer){
            this.todo(SpawnCreep,targetSpawn,body);
            return;
        }

        //判断自己能否spawn 避免过多spawn造成堵塞
        let creepsInRoom = room.getCreepsInfo();
        let transferNum = 0;
        for(let creepName in creepsInRoom){
            if(creepsInRoom[creepName].type == RoleType.Transfer){
                if(Game.creeps[creepName] != undefined){
                    transferNum++;
                }
            }
        }

        if(transferNum == 0 && Game.time % 10 == 0){
            Util.log(`警告:您的殖民地 ${HS.getCreepRoomName(this)} 没有 Transfer Creep 有可能导致殖民地运转不畅`,{
                color:COLOR_RED
            });
        }

        if(transferNum > 0){
            this.todo(SpawnCreep,targetSpawn,body);
        }
        
        

    }

    exception(e){
        switch(e.code){
            default:
                e.printStackTrace(`${this.getCreepName()} 未处理的异常`);
                return INTENT_RETURN_FAIL;
        }
    }
}



// 主入口部分 控制 Creep 的初始行为并 选择驱动 Creep
let HomesteadMain = class HomesteadMain extends Behavior{
    do(intentCreeps){


        //进行数据统计
        if(Game.time % 50 == 0){

        }

        for(let name in intentCreeps){

            //分房间驱动
            let creepInfo = HS.getCreepInfo(name);
            // console.log(JSON.stringify(creepInfo))


            let target = intentCreeps[name];
            if(target instanceof IntentCreep){
                if(target.isFree()){
                    //设置行为
                    target.set(HomesteadDefault);
                }
                
                target.next();
            }
        }


        //Link Flow
        if(Game.time % 50 == 0){
            for(let roomName in Game.rooms){
                let room = Game.rooms[roomName];
                let links = room.find(FIND_MY_STRUCTURES,{
                    filter:(i) => i.structureType == STRUCTURE_LINK,
                });
    
                let sources = room.find(FIND_SOURCES);
                sources = sources.concat(room.find(FIND_MY_STRUCTURES,{
                    filter:(i) => i.structureType == STRUCTURE_STORAGE
                }))
    
                //能量辐射运输
                links.sort(function(a,b){
                    let getLevel = function(target){//越靠近 Source或Storage 得分越高
                        let temp = 0;
                        for(let i of sources){
                            temp += target.pos.getRangeTo(i);
                        }
                        return temp;
                    }
    
                    return getLevel(b) - getLevel(a);
                })
    
                for(let i = 0; i < links.length; i++){
    
                    if(links[i].store.getUsedCapacity() / links[i].store.getCapacity() > 0.4){
                        continue;
                    }
                    
                    //距离最近的一个高等级link
                    let closestRange = 50;
                    let closest = undefined;
                    for(let j = i+1; j < links.length; j++){
                        let nowRange = links[i].pos.getRangeTo(links[j]);
                        if(nowRange < closestRange){
                            closestRange = nowRange;
                            closest = links[j];
                        }
                    }
    
                    if(closest != undefined){
                        closest.transferEnergy(links[i])
                    }
                }
            }
        }
    }
}

HS.setMain(HomesteadMain)